1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use super::*;
use crate::ui::{
    render::{ch_width, input_float_with_format},
    Hideable,
};
use arcdps::imgui::Ui;
use arcdps::{
    exports::{self, CoreColor},
    imgui::{InputTextFlags, StyleVar},
};

/// Hotkey to open window.
pub type WindowHotkey = Option<u32>;

/// Window options.
#[derive(Debug, Clone)]
pub struct WindowOptions {
    /// Whether the window is (currently) visible.
    pub visible: bool,

    /// Position of the window.
    pub position: WindowPosition,

    /// Width of the window in pixels.
    pub width: f32,

    /// Height of the window in pixels.
    pub height: f32,

    /// Whether to show the window titlebar.
    pub title_bar: bool,

    /// Whether to show the window body background.
    pub background: bool,

    /// Whether to show the window titlebar background.
    pub title_bar_background: bool,

    /// Whether to allow manually resizing the window.
    pub resize: bool,

    /// Whether to automatically resize the window according to contents.
    pub auto_resize: bool,

    /// Whether to allow scrolling.
    pub scroll: bool,

    /// Whether to show the scrollbar.
    pub scroll_bar: bool,

    /// Hotkey to open the window with.
    pub hotkey: WindowHotkey,
}

impl WindowOptions {
    /// Creates new window options.
    #[inline]
    pub fn new() -> Self {
        Self {
            visible: false,
            position: WindowPosition::default(),
            width: 0.0,
            height: 0.0,
            title_bar: true,
            background: true,
            title_bar_background: true,
            resize: true,
            auto_resize: false,
            scroll: true,
            scroll_bar: true,
            hotkey: None,
        }
    }

    /// Handles a key press event.
    ///
    /// Toggles visibility and returns `true` if the key matches the hotkey.
    #[inline]
    pub fn key_press(&mut self, key: usize) -> bool {
        if matches!(self.hotkey, Some(hotkey) if hotkey == key as u32) {
            self.toggle_visibility();
            true
        } else {
            false
        }
    }

    /// Updates the options with values from the [`Ui`]
    #[inline]
    pub fn update(&mut self, ui: &Ui) {
        // update window size values
        [self.width, self.height] = ui.window_size();
    }

    /// Renders the options menus for window style & position.
    pub fn render_options_menus(&mut self, ui: &Ui, pos: [f32; 2]) {
        let colors = exports::colors();
        let grey = colors
            .core(CoreColor::MediumGrey)
            .unwrap_or([0.5, 0.5, 0.5, 1.0]);

        ui.menu("Style", || {
            ui.text_colored(grey, "Window style");
            self.render_style_options(ui);
        });

        ui.menu("Position", || {
            ui.text_colored(grey, "Window position");
            self.position.render_select(ui, pos);
        });
    }

    /// Renders the window style options.
    pub fn render_style_options(&mut self, ui: &Ui) {
        let input_width = ch_width(ui, 12);

        ui.checkbox("Titlebar", &mut self.title_bar);
        ui.checkbox("Background", &mut self.background);
        ui.checkbox("Titlebar background", &mut self.title_bar_background);
        ui.checkbox("Scrollbar", &mut self.scroll_bar);
        ui.checkbox("Auto resize", &mut self.auto_resize);

        ui.set_next_item_width(input_width);

        let current = ui.clone_style().alpha;
        let _style = ui.push_style_var(StyleVar::Alpha(if self.auto_resize {
            0.3
        } else {
            current
        }));

        let flags = if self.auto_resize {
            InputTextFlags::READ_ONLY
        } else {
            InputTextFlags::empty()
        };

        input_float_with_format("Width", &mut self.width, STEP, STEP_FAST, FORMAT, flags);

        ui.set_next_item_width(input_width);
        input_float_with_format("Height", &mut self.height, STEP, STEP_FAST, FORMAT, flags);
    }
}

impl Default for WindowOptions {
    fn default() -> Self {
        Self::new()
    }
}

impl Hideable for WindowOptions {
    fn is_visible(&self) -> bool {
        self.visible
    }

    fn visible_mut(&mut self) -> &mut bool {
        &mut self.visible
    }
}